package parser;
import java.io.ByteArrayOutputStream;
import java.util.*;

class ByteStream extends ByteArrayOutputStream {

    public ByteStream() {
        super();
    }
    
    int baseline;
    int pending_line;
    
    void writeShort(int s) {
        if (pending_line != 0)
            write_line();
        write(s >> 8);
        write(s);
    }

    int here() {
        return size();
    }
    
    void patchShort(int location, int value) {                
        buf[location] = (byte)(value >> 8);
        buf[location+1] = (byte)value;
    }
    
    Patch branch(int opcode) {
        if (pending_line != 0)
            write_line();
        Patch p = new Patch(size());
        // Assert the opcode is valid branch?
        write(opcode);
        write(0);
        write(0);
        return p;
    }
    
    void branch_back(int opcode, int target) {
        if (pending_line != 0)
            write_line();
        int base = size();
        write(opcode);
        write(0);
        writeShort(target-base);
    }
    
    void patch(Patch p) {
        p.patch(this);
    }
    
    void clearLineNumbers() {
        pending_line = 0;
    }
    
    public void write(int b) {
        if (pending_line != 0)
            write_line();
        super.write(b);
    }
    
    void write_line() {
        super.write(Opcodes.LINE);
        super.write(pending_line >> 8);
        super.write(pending_line);
        pending_line = 0;  
    }
    
    void line (int line) {
        pending_line = line;
    }
    
    void writeUTF8(char c) {
        if (pending_line != 0)
            write_line();
        if (c < 0x80) {
            write(c);
        } else if (c < 0x800) {
            write(0xA0 | (c >> 6));
            write(0x80 | (c & 0x3f));
        } else {
            write(0xE0 | (c >> 12));
            write(0x80 | ((c >> 6) & 0x3f));
            write(0x80 | (c & 0x3f));
        }
    }
    
    int pop() {
        count--;
        return buf[count];
    }
    
}

